# -*- coding: UTF-8 -*-

import datetime

from functools import partial
from math import ceil, pow, trunc

import pandas as pd

from app import current_app, cache
from app.datav.models.monitor_metrics import MonitorMetrics
from app.datav.utils.elastic import Elastic
from app.datav.utils.prometheus import Prometheus
from common.utils_base import AppUtils, DtUtil

__all__ = ['Monitor']


class Monitor(object):

    def __init__(self):
        pass

    @property
    def today(self):
        return (datetime.date.today()).strftime("%Y.%m.%d")

    def datetime_point(self, seconds):
        return (datetime.datetime.now().replace(microsecond=0) - datetime.timedelta(seconds=seconds),
                datetime.datetime.now().replace(microsecond=0))

    def datetime_minmax(self, before=0):
        return (datetime.datetime.combine(datetime.date.today() - datetime.timedelta(days=before), datetime.time.min),
                datetime.datetime.combine(datetime.date.today() - datetime.timedelta(days=before), datetime.time.max))

    def max_ceil(self, num, prec=2):
        '''
        https://www.rokub.com/73716.html
        数字取整为10的倍数向上取整
        :param num:hh
        :param prec:
        :return:
        '''
        if len(str(num)) <= prec:
            return num
        return ceil(num / pow(10, prec)) * pow(10, prec)

    @cache.cached(timeout=60, key_prefix='product_code')
    def product_code(self, item):
        index = f'logstash-openresty_access-{self.today}'
        datetime_start, datetime_end = self.datetime_point(seconds=300)
        try:
            elastic = Elastic(server=current_app.config.get('ES_MONITOR_SERVER'), port='9200')
            return elastic.product_code(item, index, datetime_start, datetime_end)
        except Exception as e:
            return False

    @cache.cached(timeout=60, key_prefix='applied_notification')
    def applied_notification(self, item):
        '''
        :param item: japi_qpm_today
        :return:
        '''
        datetime_start, datetime_end = self.datetime_point(seconds=7200)
        data = MonitorMetrics.get_item_data(item, datetime_start, datetime_end)
        if not AppUtils.is_empty(data):
            DtUtil_collection_cst = partial(DtUtil.collection, cst=True, dtype='cst_str')
            dict_data = {'datetime': pd.DataFrame(data).get('create_time').apply(DtUtil_collection_cst),
                         'value': pd.DataFrame(data).get('value')}
            return pd.DataFrame(dict_data).dropna(axis=0, how='any').to_numpy().tolist()
        return False

    @cache.cached(timeout=60, key_prefix='req_time')
    def req_time(self, item):
        server = ['172.20.40.20']
        index = f'logstash-openresty_access-{self.today}'
        datetime_start, datetime_end = self.datetime_point(seconds=300)
        try:
            elastic = Elastic(server=server, port='9200')
            return elastic.req_time(item, index, datetime_start, datetime_end)
        except Exception as e:
            print(e)
            return False

    @cache.cached(timeout=60, key_prefix='map_applied')
    def map_applied(self, item):
        index = {'sms_index_name': f'logstash-tc-{self.today}',
                 'access_index_name': f'logstash-openresty_access-{self.today}'}
        datetime_start, datetime_end = self.datetime_point(seconds=180)
        try:
            elastic = Elastic(server=current_app.config.get('ES_MONITOR_SERVER'), port='9200')
            return elastic.map_applied(index, datetime_start, datetime_end)
        except Exception as e:
            print(e)
            return False

    @cache.cached(timeout=60, key_prefix='japi_qpm')
    def japi_qpm(self, item):
        today = self.__japi_qpm_today(item)
        yesterday = self.__japi_qpm_yesterday(item)
        max = today.get('max') if today.get('max') >= yesterday.get('max') else yesterday.get('max')
        if not AppUtils.is_empty(max):
            return {"today": today.get("data"), "yesterday": yesterday.get("data"),
                    "max": self.max_ceil(max, len(str(trunc(max))) - 1)}

        return False

    @cache.cached(timeout=60, key_prefix='japi_jvm_threads_busy')
    def japi_jvm_threads_busy(self, item):
        result = []
        # promql = 'tomcat_threadpool_currentthreadsbusy{job="jrocket2-exporter",port="8080"}'
        # 当前线程数
        # promql = 'jvm_threads_current{job="jrocket2-exporter"}'
        # promql = "jvm_threads_current{pod =~'document.*'}"
        promql = "jvm_threads_current{job='jrocket2'}"
        prometheus = Prometheus(host=current_app.config.get('PROMETHEUS_HOST'),
                                port=current_app.config.get('PROMETHEUS_PORT'))
        datetime_start, datetime_end = self.datetime_point(seconds=3600)
        try:
            # datas = prometheus.query_range(
            #     promql=promql,
            #     # 时间数据为UTC 00:00时区
            #     datatime_start=DtUtil.collection(datetime_start, cst=False, dtype='utc_ts'),
            #     datatime_end=DtUtil.collection(datetime_end, cst=False, dtype='utc_ts'),
            #     step='1m').get("data").get("result")
            datas = prometheus.query_range(
                promql=promql,
                # 时间数据为UTC 00:00时区
                datatime_start=DtUtil.collection(datetime_start, cst=False, dtype='utc_ts'),
                datatime_end=DtUtil.collection(datetime_end, cst=False, dtype='utc_ts'),
                step='1m').get("data").get("result")
            from pprint import pprint
            pprint(datas)
        except Exception as e:
            print(e)
            return False

        for data in datas:
            pd_data = pd.DataFrame(data.get('values'), columns=['timestamp', 'value'])
            # 时间数据为UTC 00:00时区,增加8小时
            pd_data['timestamp'] = (
                    pd.to_datetime(pd_data['timestamp'], unit='s') + pd.Timedelta(28000, unit='s')).astype(str)
            result.append(
                {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
                 'name': data.get('metric').get('instance')})
            # result.append(
            #     {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
            #      'name': data.get('metric').get('pod').split('-')[1:2]})

        return result

    @cache.cached(timeout=60, key_prefix='rds_pg_cpu_usage')
    def rds_pg_cpu_usage(self, item):
        result = []
        # promql = "aliyun_acs_rds_dashboard_CpuUsage{instanceId=~'pg[m|r].*'}"
        promql = "sum by(instance) (rate(node_cpu_seconds_total{hostname=~'.*jrocket2.*',mode!='idle',mode!='iowait',mode!='steal'}[3m])) * 100 * 1.4"
        prometheus = Prometheus(host=current_app.config.get('PROMETHEUS_HOST'),
                                port=current_app.config.get('PROMETHEUS_PORT'))
        datetime_start, datetime_end = self.datetime_point(seconds=3600)
        try:
            datas = prometheus.query_range(
                promql=promql,
                # 时间数据为UTC 00:00时区
                datatime_start=DtUtil.collection(datetime_start, cst=False, dtype='utc_ts'),
                datatime_end=DtUtil.collection(datetime_end, cst=False, dtype='utc_ts'),
                step='1m').get("data").get("result")
        except Exception as e:
            print(e)
            return False

        for data in datas:
            pd_data = pd.DataFrame(data.get('values'), columns=['timestamp', 'value'])
            # 时间数据为UTC 00:00时区,增加8小时
            pd_data['timestamp'] = (
                    pd.to_datetime(pd_data['timestamp'], unit='s') + pd.Timedelta(28000, unit='s')).astype(str)
            # result.append(
            #     {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
            #      'name': data.get('metric').get('instanceId')})
            result.append(
                {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
                 'name': data.get('metric').get('instance')})

        return result

    @cache.cached(timeout=60, key_prefix='rds_pg_mem_usage')
    def rds_pg_mem_usage(self, item):
        result = []
        # promql = "aliyun_acs_rds_dashboard_MemoryUsage{instanceId =~'pg[m|r].*'}"
        promql = "(1 - (node_memory_MemAvailable_bytes{hostname=~'.*jrocket2.*',job='node-exporter'} / node_memory_MemTotal_bytes{hostname=~'.*jrocket2.*',job='node-exporter'})) * 100"
        prometheus = Prometheus(host=current_app.config.get('PROMETHEUS_HOST'),
                                port=current_app.config.get('PROMETHEUS_PORT'))
        datetime_start, datetime_end = self.datetime_point(seconds=3600)
        try:
            datas = prometheus.query_range(
                promql=promql,
                # 时间数据为UTC 00:00时区
                datatime_start=DtUtil.collection(datetime_start, cst=False, dtype='utc_ts'),
                datatime_end=DtUtil.collection(datetime_end, cst=False, dtype='utc_ts'),
                step='1m').get("data").get("result")
        except Exception as e:
            print(e)
            return False

        for data in datas:
            pd_data = pd.DataFrame(data.get('values'), columns=['timestamp', 'value'])
            # 时间数据为UTC 00:00时区,增加8小时
            pd_data['timestamp'] = (
                    pd.to_datetime(pd_data['timestamp'], unit='s') + pd.Timedelta(28000, unit='s')).astype(str)
            # result.append(
            #     {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
            #      'name': data.get('metric').get('instanceId')})
            result.append(
                {'data': pd_data.dropna(axis=0, how='any').to_numpy().tolist(),
                 'name': data.get('metric').get('instance')})

        return result

    def __japi_qpm_today(self, item):
        '''
        :param item: japi_qpm_today
        :return: tuple data  max
        '''
        datetime_min, datetime_max = self.datetime_minmax(before=0)
        data = MonitorMetrics.get_item_data(item, datetime_min, datetime_max)
        if not AppUtils.is_empty(data):
            df = pd.DataFrame(data)
            dict_data = {'datetime': df['create_time'].astype(str),
                         'value': df['value'].diff()}

            return {"data": pd.DataFrame(dict_data).dropna(axis=0, how='any').to_numpy().tolist(),
                    "max": df['value'].diff().dropna(axis=0, how='any').max()}

        return {"data": [], "max": 0}

    def __japi_qpm_yesterday(self, item):
        '''
        :param item: japi_qpm_yesterday
        :return: tuple data  max
        '''
        datetime_min, datetime_max = self.datetime_minmax(before=1)
        data = MonitorMetrics.get_item_data(item, datetime_min, datetime_max)
        if not AppUtils.is_empty(data):
            df = pd.DataFrame(data)
            dict_data = {'datetime': (df['create_time'] + pd.Timedelta(1, unit='D')).astype(str),
                         'value': df['value'].diff()}

            return {"data": pd.DataFrame(dict_data).dropna(axis=0, how='any').to_numpy().tolist(),
                    "max": df['value'].diff().dropna(axis=0, how='any').max()}

        return {"data": [], "max": 0}


if __name__ == "__main__":
    monitor = Monitor()
    print(monitor.japi_jvm_threads_busy('test'))
